#ifndef __MIXINABLE_HH__
#define __MIXINABLE_HH__

#include <boost/scoped_ptr.hpp>

namespace Common
{
    
namespace Patterns
{

/**
 * @struct Mixinable
 * @brief Enables inside the next class to be mixed by the mixins objects.
 * This class provides a mechanism to compute table of pointers to each mixin.
 * Only precondition is to provide staticly generated collection of all mixins
 * and give it as TAllMixins template parameter.
 */
template< class BASE, typename TAllMixins >
struct Mixinable
{
    /// type that describes object that holds and compute mixins pointers
    typedef typename TAllMixins::template TypesTable< BASE > TypesTable;

    /**
     * @brief Default ctor.
     * Counts address that is a beginning of the derived class.
     * @note It works for both static and heap objects.
     */
    Mixinable( void )
    {
        intptr_t diff = ( intptr_t )( BASE* ) 1 - ( intptr_t )( Mixinable< BASE, TAllMixins >* )( BASE* ) 1;
        iBase = ( BASE* ) ( ( intptr_t ) this + diff );
    }

    /**
     * @brief Default dtor.
     * It is here because we need polymorphism. And its empty because we don't need
     * to destroy anything here.
     */
    virtual ~Mixinable( void )
    {
    }

    /**
     * @brief Method that cast's this pointer to a wanted mixin pointer.
     * It uses staticly generated and dynamicly precalculated container of pointers.
     * @note No need to use dynamic_cast anymore.
     */
    template< typename T >
    T* castTo( void )
    {
        if( !iTypesTable )
        {
            iTypesTable.initialize( iBase );
        }

        return ( T* )iTypesTable[ TAllMixins::template GetMixinId< BASE, T >::id ];
    }

private:
    /// Pointer to a computed base class object
    BASE*               iBase;
    /// Container for pointers to mixins
    TypesTable          iTypesTable;
};

} // namespace Patterns
} // namespace Common

#endif